import EventEmitter from '@/utils/EventEmitter'
import {
  UpscaleModel,
  RespWorkerMessage,
  RunBack,
  SendWorkerMessage,
  ImageUpscaleParams,
  ModelInfo,
} from './types'
// import ImageUpScaleWorker from './worker?worker'
import { createResolvablePromise } from '@/utils/common'
import { showToast } from '@/utils/toast'
/**
 * worker -> main 消息类型
 */
type WorkerMessage = {
  getBackend: (runBack: RunBack) => any
  getModelList: (list: ModelInfo[]) => any
  predictProgress: (data: {
    /**
     * 执行的模型队列数量
     */
    modelQueryCount: number
    /**
     * 当前执行的模型下标
     */
    currentQuery: number
    /**
     * 当前模型执行进度
     */
    progress: number
  }) => any
  modelStatusChange: (data: ModelInfo) => any
  predictResult: (data: {
    result: Uint8ClampedArray
    width: number
    height: number
    predictTime: number
  }) => any
  runStatusChange: (status: boolean) => any
  setBackend: (flag: boolean) => any
  error: (error: string) => any
  modelLoadProgress: (data: ModelInfo) => any
  ready: (data: boolean) => any
}
const workerEmitter = new EventEmitter<WorkerMessage>()
let worker: Worker = {} as any
if (typeof window !== 'undefined') {
  worker = new Worker(new URL('./worker.ts', import.meta.url))
  worker.onerror = (event) => {
    workerEmitter.emit('error', event.message)
  }
}

function workerEmitterInit() {
  worker.onerror = (event) => {
    workerEmitter.emit('error', event.message)
  }
  worker.onmessage = (event) => {
    const { type, data } = event.data as RespWorkerMessage
    workerEmitter.emit(type, data)
  }
}
function sendToWorker(message: SendWorkerMessage) {
  worker.postMessage(message)
}
workerEmitterInit()
class ImageUpscaleManager {
  private running = false
  private ready = false
  public getRunning() {
    return this.running
  }
  /**
   * webwork是否初始化完成
   * @returns
   */
  public getReady() {
    return this.ready
  }

  constructor() {
    workerEmitter.on('error', (err) => {
      showToast(err)
    })
    workerEmitter.on('runStatusChange', (status) => {
      this.running = status
    })
    workerEmitter.on('ready', (status) => {
      console.log('webwork init success')

      this.ready = status
    })
  }
  async getBackend(): Promise<RunBack> {
    const [p, resolve] = createResolvablePromise<RunBack>()
    workerEmitter.once('getBackend', resolve)
    sendToWorker({
      type: 'getBackend',
    })
    return p
  }
  async setBackend(backend: RunBack): Promise<boolean> {
    if (!this.ready) {
      showToast('程序初始化中，请稍后')
      return false
    }
    const [p, resolve] = createResolvablePromise<boolean>()
    workerEmitter.once('setBackend', resolve)
    sendToWorker({
      type: 'setBackend',
      data: backend,
    })
    return p
  }
  async getModelList() {
    const [p, resolve] = createResolvablePromise<ModelInfo[]>()
    workerEmitter.once('getModelList', resolve)
    sendToWorker({
      type: 'getModelList',
    })
    return p
  }
  /**
   * 请求加载model
   * @param model
   */
  async requestLoadModel(model: UpscaleModel) {
    if (!this.ready) {
      showToast('程序初始化中，请稍后')
      return
    }
    sendToWorker({
      type: 'requestLoadModel',
      data: model,
    })
  }
  predict(params: ImageUpscaleParams) {
    if (!this.ready) {
      showToast('程序初始化中，请稍后')
      return
    }
    if (this.running) {
      showToast('模型正在运行,请稍后')
      return
    }
    sendToWorker({
      type: 'predict',
      data: params,
    })
  }
  stop() {
    if (!this.ready) {
      showToast('程序初始化中，请稍后')
      return false
    }
    sendToWorker({ type: 'stop' })
  }
  get event() {
    return workerEmitter
  }
}

export default new ImageUpscaleManager()
